/**
 * 
 */
package com.hj.service;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hibernate.internal.SessionImpl;
import org.springframework.stereotype.Component;

/**
 * @author huangjian
 */
@Component
@SuppressWarnings("rawtypes")
public class CommonServiceImpl implements CommonService {
	private Logger log = LogManager.getLogger(getClass());
	@PersistenceContext
	private EntityManager em;

	@Override
	public <T> T findByPK(Class<T> entityClass, Object primaryKey) {
		return em.find(entityClass, primaryKey);
	}

	@Override
	public List findBy(String qlString, Map<String, Object> parameter) {
		Query query = em.createQuery(qlString);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.getResultList();
	}

	@Override
	public <T> List<T> findBy(String qlString, Class<T> resultClass, Map<String, Object> parameter) {
		TypedQuery<T> query = em.createQuery(qlString, resultClass);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.getResultList();
	}

	@Override
	public List findBy(String qlString, Object... obj) {
		Query query = em.createQuery(qlString);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.getResultList();
	}

	@Override
	public <T> List<T> findBy(String qlString, Class<T> resultClass, Object... obj) {
		TypedQuery<T> query = em.createQuery(qlString, resultClass);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.getResultList();
	}

	@Override
	public List findBySql(String sqlString, Map<String, Object> parameter) {
		Query query = em.createNativeQuery(sqlString);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.getResultList();
	}

	@Override
	public List findBySql(String sqlString, Object... obj) {
		Query query = em.createNativeQuery(sqlString);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.getResultList();
	}

	@Override
	public List findBySql(String sqlString, Class resultClass, Map<String, Object> parameter) {
		Query query = em.createNativeQuery(sqlString, resultClass);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.getResultList();
	}

	@Override
	public List findBySql(String sqlString, Class resultClass, Object... obj) {
		Query query = em.createNativeQuery(sqlString, resultClass);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.getResultList();
	}

	@Override
	public List findByNamedQuery(String name, Map<String, Object> parameter) {
		Query query = em.createNamedQuery(name);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.getResultList();
	}

	@Override
	public List findByNamedQuery(String name, Object... obj) {
		Query query = em.createNamedQuery(name);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.getResultList();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T findUnique(String qlString, Object... obj) {
		List list = findBy(qlString, obj);
		if (list.size() == 1) {
			return (T) list.get(0);
		}
		return null;
	}

	@Override
	public int batchExcute(String qlString, Map<String, Object> parameter) {
		Query query = em.createQuery(qlString);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.executeUpdate();
	}

	@Override
	public int batchExcute(String qlString, Object... obj) {
		Query query = em.createQuery(qlString);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.executeUpdate();
	}

	@Override
	public int batchExcuteSql(String sqlString, Map<String, Object> parameter) {
		Query query = em.createNativeQuery(sqlString);
		for (String param : parameter.keySet()) {
			query.setParameter(param, parameter.get(param));
		}
		return query.executeUpdate();
	}

	@Override
	public int batchExcuteSql(String sqlString, Object... obj) {
		Query query = em.createNativeQuery(sqlString);
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i + 1, obj[i]);
		}
		return query.executeUpdate();
	}

	//"{ call powerdesk.bid_temp_pkg.validateBidDivision(?,?,?,?)}"
	@Override
	public boolean executeStoreProcedure(String name, Map<Integer, String> map) {
		SessionImpl session = (SessionImpl) em.getDelegate();
		Connection conn = session.connection();
		CallableStatement callableStatement = null;
		try {
			log.info("excute:" + name);
			callableStatement = conn.prepareCall(name);
			for (int i = 0; i < map.size(); i++) {
				callableStatement.setString(i + 1, map.get(i));
			}
			callableStatement.execute();
		} catch (Exception e) {
			log.error(e);
			throw new RuntimeException(e);
		} finally {
			try {
				if (callableStatement != null) {
					callableStatement.close();
				}
			} catch (Exception e2) {
				log.error(e2);
				throw new RuntimeException(e2);
			}
		}
		return true;
	}
}
